/* -----------------------------------------------------------------------------
 * Copyright (c) 2014 ARM Ltd.
 *
 * This software is provided 'as-is', without any express or implied warranty. 
 * In no event will the authors be held liable for any damages arising from 
 * the use of this software. Permission is granted to anyone to use this 
 * software for any purpose, including commercial applications, and to alter 
 * it and redistribute it freely, subject to the following restrictions:
 *
 * 1. The origin of this software must not be misrepresented; you must not 
 *    claim that you wrote the original software. If you use this software in
 *    a product, an acknowledgment in the product documentation would be 
 *    appreciated but is not required. 
 * 
 * 2. Altered source versions must be plainly marked as such, and must not be 
 *    misrepresented as being the original software. 
 * 
 * 3. This notice may not be removed or altered from any source distribution.
 *   
 *
 * $Date:        15. April 2014
 * $Revision:    V1.00
 *  
 * Project:      Flash Programming Functions for STMicroelectronics STM32F4xx Flash
 * --------------------------------------------------------------------------- */

/* History:
 *  Version 1.00
 *    Initial release
 */

#include "FlashOS.H" // FlashOS Structures

#include <stdint.h>
#include <string.h>

#include "main.h"
#include "quadspi.h"
#include "w25q64jv.h"

extern int SystemClock_Config(void);

HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
  return HAL_OK;
}

uint32_t HAL_GetTick(void)
{
  return 10;
}

/*
 *  Initialize Flash Programming Functions
 *    Parameter:      adr:  Device Base Address
 *                    clk:  Clock Frequency (Hz)
 *                    fnc:  Function Code (1 - Erase, 2 - Program, 3 - Verify)
 *    Return Value:   0 - OK,  1 - Failed
 */
uint32_t base_adr = 0;
int Init(unsigned long adr, unsigned long clk, unsigned long fnc)
{
  base_adr = adr;

  SystemInit();
  // HAL_Init();

  SystemClock_Config();
  // MX_GPIO_Init();

  MX_QUADSPI_Init();
  //if (QSPI_W25Q64JV_Reset() != QSPI_OK)
  //{
  //  return (1);
  //}
  QSPI_W25Q64JV_EnableMemoryMappedMode();
  return (0);
}

/*
 *  De-Initialize Flash Programming Functions
 *    Parameter:      fnc:  Function Code (1 - Erase, 2 - Program, 3 - Verify)
 *    Return Value:   0 - OK,  1 - Failed
 */

int UnInit(unsigned long fnc)
{
  MX_QUADSPI_Init();
  QSPI_W25Q64JV_EnableMemoryMappedMode();
  //if (QSPI_W25Q64JV_Reset() != QSPI_OK)
  //{
  //  return (1);
  //}
  return (0);
}

/*
 *  Erase complete Flash Memory
 *    Return Value:   0 - OK,  1 - Failed
 */

int EraseChip(void)
{
  MX_QUADSPI_Init();
  QSPI_W25Q64JV_EraseChip();
  QSPI_W25Q64JV_EnableMemoryMappedMode();
  return (0);
}

/*
 *  Erase Sector in Flash Memory
 *    Parameter:      adr:  Sector Address
 *    Return Value:   0 - OK,  1 - Failed
 */

int EraseSector(unsigned long adr)
{
  MX_QUADSPI_Init();
  if (QSPI_W25Q64JV_EraseBlock(adr - base_adr) != QSPI_OK)
  {
    return (1);
  }
  QSPI_W25Q64JV_EnableMemoryMappedMode();
  return (0);
}

/*
 *  Program Page in Flash Memory
 *    Parameter:      adr:  Page Start Address
 *                    sz:   Page Size
 *                    buf:  Page Data
 *    Return Value:   0 - OK,  1 - Failed
 */

int ProgramPage(unsigned long adr, unsigned long sz, unsigned char *buf)
{
  MX_QUADSPI_Init();
  if (QSPI_W25Q64JV_Write(buf, adr - base_adr, sz) != QSPI_OK)
  {
    return (1);
  }
  QSPI_W25Q64JV_EnableMemoryMappedMode();
  return (0);
}

#if 1
unsigned long Verify(unsigned long adr, unsigned long sz, unsigned char *buf)
{
  uint8_t *p = (uint8_t *)adr;
  //QSPI_W25Q64JV_EnableMemoryMappedMode();

  for (int i = 0; i < sz; i++)
  {
    if (*p != buf[i])
    {
      return ((unsigned long)p);
    }
    p++;
  }

  return (adr + sz);
}
#endif
